<?php

/* Includes */	
require_once "DBConfig.php";

/* Actual database represented in PHP module */
class Database
{
	/* Member variables */
	private $mysqli = NULL;
	
	/* Connects to a mysql database with the information provded by a config object*/
	public function Connect(DBConfig $config)
	{
		// Open a connection to $config->m_db
		$this->mysqli = new mysqli($config->m_host, $config->m_user, $config->m_pass, $config->m_db);
		
		// Check for any errors with the connection, and throw an exception if any was found
		if ($this->mysqli->connect_error)
			throw new Exception($this->mysqli->connect_error);
		
		// Set the proper charset for the information held by the database
		$this->mysqli->set_charset("utf8");
		
		// If all went well, return true to indicate so
		return true;
	}
	
	/* Takes and prepares a query and returns a mysqli::stmt */
	public function Prepare($sqlQuery)
	{
		$return = $this->mysqli->prepare($sqlQuery);
		
		if ($return == false)
			throw new Exception($this->mysqli->error);
			
		return $return;
	}
	
	/* Executes the query passed in */
	public function ExecuteSelectOneQuery(mysqli_stmt $stmt)
	{		
		// Check for errors with the preperation
		if ($stmt === false)
			throw new Exception($this->mysqli->error);
		
		// Execute the query
		if ($stmt->execute() == false)
			throw new Exception($this->mysqli->error);
		
		$return = 0;
		
		// Bind the query result to $ret that is passed via reference and then fetch it
		$stmt->bind_result($return);
		$stmt->fetch();
		$stmt->close();
		
		// If all executed well
		return $return;
	}
	
	/* Executes the query passed in */
	public function ExecuteRemoveOneQuery(mysqli_stmt $stmt)
	{		
		// Check for errors with the preperation
		if ($stmt === false)
			throw new Exception($this->mysqli->error);
		
		// Execute the query
		if ($stmt->execute() == false)
			throw new Exception($this->mysqli->error);
		
		$stmt->close();
		
		// If all executed well
		return true;
	}
	
	/* Executes the query passed in */
	public function ExecuteSelectOneColQuery(mysqli_stmt $stmt)
	{		
		// Check for errors with the preperation
		if ($stmt === false)
			throw new Exception($this->mysqli->error);
		
		// Execute the query
		if ($stmt->execute() == false)
			throw new Exception($this->mysqli->error);
		
		$return = array();
		$col;
		
		// Bind the query result to $ret that is passed via reference and then fetch it
		$stmt->bind_result($col);
		
		while ($stmt->fetch())
			$return[] = $col;
			
		$stmt->close();
		
		// If all executed well
		return $return;
	}
	
	/* Executes the query passed in */
	public function ExecuteSelectUserAndPass(mysqli_stmt $stmt)
	{		
		// Check for errors with the preperation
		if ($stmt === false)
			throw new Exception($this->mysqli->error);
		
		// Execute the query
		if ($stmt->execute() == false)
			throw new Exception($this->mysqli->error);
		
		$return = array();
		$user;
		$pass;
		
		// Bind the query result to $ret that is passed via reference and then fetch it
		$stmt->bind_result($user, $pass);
		$stmt->fetch();
		
		$return[] = $user;
		$return[] = $pass;
			
		$stmt->close();
		
		// If all executed well
		return $return;
	}
	
	/* Executes the query passed in */
	/*public function GetWholeTable($table)
	{
		// prepare statement
		$stmt = $this->Prepare("SELECT * FROM " . $table);
		
		// Check for errors with the preperation
		if ($stmt == false)
			throw new Exception($this->mysqli->error);
		
		// Execute the query
		if ($stmt->execute() == false)
			throw new Exception($this->mysqli->error);
		
		$md = $stmt->result_metadata();
		$fieldCount = $md->field_count;
		$fields = $md->fetch_fields();
		
		$return = array();
		//'$stmt->bind_result(';
		
        foreach($fields as $field)
		{
			$stmt2 = $this->Prepare("SELECT * FROM " . $field->name);
			
			// Check for errors with the preperation
			if ($stmt2 == false)
				throw new Exception($this->mysqli->error);
			
			// Execute the query
			if ($stmt2->execute() == false)
				throw new Exception($this->mysqli->error);
			
            $stmt2->bind_results($return[$field->name]);
		}
		
		$stmt->close();
		
		return $fields;
	}*/
	
	/* Takes a mysqli::stmtExecutes a insert query returns the primary key of the inserted post */
	public function ExecuteInsertQuery(mysqli_stmt $stmt)
	{
		// Check for errors with the preperation
		if ($stmt === false)
			throw new Exception($this->mysqli->error);
		
		if ($stmt->execute() == false)
			throw new Exception($this->mysqli->error);
		
		$return = $stmt->insert_id;
		
		$stmt->close();
		
		return $return;
	}
	
	/* Close the databaseconnection and return the state which it closed in */
	public function Close()
	{
		return $this->mysqli->close();
	}
	
	/* Tests all teh functionality of the database */
	public static function Test(DBConfig $dbConfig)
	{
		// System under test
		$sut = new Database();
		$hasErrors = false;
		
		// Test "Connect()" function
		if (!$sut->Connect($dbConfig))
		{
			echo "<div>Fail! Function Connect() not working as intended!</div>";
			$hasErrors = true;
        }
        
		// Prepare a statement with a query (Before inserton)
		$stmt = $sut->Prepare("SELECT COUNT(*) FROM TestTable");
        $beforeInsertion = $sut->ExecuteSelectOneQuery($stmt);
		
		// Prepare a sql query and test "ExecuteInsertQuery()" function
		$stmt = $sut->Prepare("INSERT INTO TestTable (testTableID, testValue) VALUES (DEFAULT, 1)");
        $sut->ExecuteInsertQuery($stmt);
        
		//  Prepare a statement with a query (After inserton)
		$stmt = $sut->Prepare("SELECT COUNT(*) FROM TestTable");
        $afterInsertion = $sut->ExecuteSelectOneQuery($stmt);
		
		if ($afterInsertion != $beforeInsertion + 1)
		{
			echo "<div>Error! Function ExecuteInsertQuery() not working as intended!</div>";
			$hasErrors = true;
		}
		
		try 
		{
			$stmt = $sut->Prepare("SELECT TestValue FROM TestTable");
			$sut->ExecuteSelectOneColumnQuery($stmt);
		}
		catch (exception $e)
		{
			echo "<div>Error! Function SelectOneColumn not working properly!</div>";
			$hasErrors = true;
		}
		
		// Test "Close()" function
        if ($sut->Close() == false)
        {
			echo "<div>Database Close failed</div>";
			$hasErrors = true;
        }
		
		// If all test were successfull
		return !$hasErrors;
	}
}
